﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics.Eventing.Reader;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Castle.Core.Internal;
using FD.RemoteAssistant.Core;
using FD.RemoteAssistant.Core.Extensions;
using FD.RemoteAssistant.Entities;
using FD.RemoteAssistant.Entities.Extensions;
using FDRemoteAssistant2.Extensions;
using FDRemoteAssistant2.Manager;

namespace FDRemoteAssistant2
{
    /*
     * CreatedOn: 2018-05-15
     * CreatedBy: Jackie Lee(天宇遊龍)
     */
    public partial class FormSettingList : Form
    {
        private const int WM_SYSKEYDOWN = 0x0104;
        private const int WM_KEYDOWN = 0x0100;
        private Action<string, string> _connectAction;
        private Action<IRemoteSetting, AddToMenuItemType> _newConnectTo;

        #region 初始化
        public FormSettingList(Action<string, string> itemConnectTo, Action<IRemoteSetting, AddToMenuItemType> newConnectTo)
        {
            _connectAction = itemConnectTo;
            _newConnectTo = newConnectTo;
            InitializeComponent();
            Init();
        }

        private void Init()
        {
            Text = $"配置信息 - {Application.ProductName}";
            FormBorderStyle = FormBorderStyle.FixedToolWindow;
            StartPosition = FormStartPosition.CenterParent;

            dgvSettings.AllowUserToDeleteRows = true;
            dgvSettings.AutoGenerateColumns = false; // 取消自动排序列
            dgvSettings.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            dgvSettings.EditMode = DataGridViewEditMode.EditProgrammatically;
            dgvSettings.CellFormatting += DgvSettings_CellFormatting;
            dgvSettings.CellValueChanged += DgvSettings_CellValueChanged;
            dgvSettings.CellDoubleClick += DgvSettings_CellDoubleClick;
            dgvSettings.CellContentClick += DgvSettings_CellContentClick;
            dgvSettings.RowPostPaint += DgvSettings_RowPostPaint;

            InitMenu();

            AddModelColumn<RemoteSetting>();

            dpSettings.NavToFirst += (sender, e) =>
              {
                  BindData(dpSettings.GetResult<IRemoteSetting>());
              };
            dpSettings.NavToPre += (sender, e) =>
            {
                BindData(dpSettings.GetResult<IRemoteSetting>());
            };
            dpSettings.NavToNext += (sender, e) =>
            {
                BindData(dpSettings.GetResult<IRemoteSetting>());
            };
            dpSettings.NavToLast += (sender, e) =>
            {
                BindData(dpSettings.GetResult<IRemoteSetting>());
            };
            BindData(RuntimeContext.Current.RemoteSettings, true);

            cmbStatus.Items.Add(new SettingStatus { Text = "--选择--", Value = 0 });
            cmbStatus.Items.Add(new SettingStatus { Text = "可用", Value = 1 });
            cmbStatus.Items.Add(new SettingStatus { Text = "禁用", Value = 2 });
            cmbStatus.DisplayMember = "Text";
            cmbStatus.ValueMember = "Value";
            cmbStatus.SelectedIndex = 0;
            cmbStatus.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        private ContextMenuStrip _contextMenu;
        private const string MENU_NEW = "新建";
        private const string MENU_DELETE = "删除";
        private const string MENU_COPY_PWD = "复制密码";

        private void InitMenu()
        {
            _contextMenu = new ContextMenuStrip();
            _contextMenu.Items.Add(MENU_NEW);
            _contextMenu.Items.Add(new ToolStripSeparator());
            _contextMenu.Items.Add(MENU_DELETE);
            _contextMenu.Items.Add(new ToolStripSeparator());
            _contextMenu.Items.Add(MENU_COPY_PWD);

            _contextMenu.ItemClicked += _contextMenu_ItemClicked;
            //dgvSettings.CellMouseDown += DgvSettings_CellMouseDown;
            dgvSettings.ContextMenuStrip = _contextMenu;
        }
        #endregion

        #region 事件处理

        #region 窗体事件
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_SYSKEYDOWN)
            {
                switch (keyData)
                {
                    case Keys.Escape:
                        Close();
                        return false;
                }
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }



        #endregion

        #region DataGridView事件
        private void DgvSettings_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            var num = (dpSettings.PageIndex - 1) * PageSize + e.RowIndex + 1;
            Rectangle rect = new Rectangle(e.RowBounds.Location.X + 14, e.RowBounds.Location.Y, e.RowBounds.Width - 4, e.RowBounds.Height);
            TextRenderer.DrawText(e.Graphics, (num).ToString(), dgvSettings.RowHeadersDefaultCellStyle.Font,
                rect, dgvSettings.RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
        }

        private void DgvSettings_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1)
            {
                return;
            }

            var dataGridViewRow = dgvSettings.Rows[e.RowIndex];
            var cellUserName = dataGridViewRow.Cells["UserName"]?.Value.ToString();
            var cellSever = dataGridViewRow.Cells["Server"]?.Value.ToString();
            var cellGroup = dataGridViewRow.Cells["Group"]?.Value.ToString();
            var cellName = dataGridViewRow.Cells["Name"]?.Value.ToString();
            var cItem = (DataColumnItem)dgvSettings.Columns[e.ColumnIndex].Tag;
            if ("操作" == cItem.Text)
            {
                var tip = cellGroup.IsNullOrEmpty() ? "" : $"{cellGroup}:";
                var tipText = $"{tip}{cellUserName}-{cellSever}";
                var title = cellName.IsNullOrEmpty() ? tipText : cellName;
                _connectAction?.Invoke(title, tipText);
            }
        }
        private void DgvSettings_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                var userName = RowItemValue(dgvSettings, e.RowIndex, "UserName");//dgvSettings.Rows[e.RowIndex].Cells["UserName"].Value.ToString();
                var server = RowItemValue(dgvSettings, e.RowIndex, "Server");//dgvSettings.Rows[e.RowIndex].Cells["Server"].Value.ToString();
                //var group = RowItemValue(dgvSettings, e.RowIndex, "Group");
                //var name = RowItemValue(dgvSettings, e.RowIndex, "Name");

                var item = RuntimeContext.Current.FirstOrDefault(a => a.Server == server && a.UserName == userName);
                if (item == null)
                {
                    this.MsgBox("所在行数据异常");
                    return;
                }
                using (var formSettings = new FormSettings(item))
                {
                    if (DialogResult.OK == formSettings.ShowDialog())
                    {
                        int index = RuntimeContext.Current.RemoveSetting(item);
                        RuntimeContext.Current.AddSetting(formSettings.Result, index);
                        //BindData(RuntimeContext.Current.RemoteSettings, bRefresh: true);
                        btnOK_Click(sender, e);
                        FDHelper.Current.Save();
                    }
                }
            }
        }
        private void DgvSettings_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == -1)
                return;
            var cell = dgvSettings.Rows[e.RowIndex].Cells[e.ColumnIndex];
            cell.Tag = cell.Value;
        }

        private void DgvSettings_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            var dcItem = (DataColumnItem)dgvSettings.Columns[e.ColumnIndex].Tag;
            if (dcItem.DataColumnType == DataColumnType.Password)
            {
                var value = e.Value?.ToString();
                if (!value.IsNullOrEmpty())
                {
                    e.Value = "******";
                    dgvSettings.Rows[e.RowIndex].Cells[e.ColumnIndex].Tag = e.Value;
                }
            }
        }

        #endregion

        #region 菜单事件
        private void _contextMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            _contextMenu.Visible = false;
            if (e.ClickedItem.Text == MENU_DELETE)
            {
                var row = dgvSettings.CurrentRow;
                if (row == null)
                    return;

                var userName = RowItemValue(dgvSettings, row.Index, "UserName");
                var server = RowItemValue(dgvSettings, row.Index, "Server");
                //var group = RowItemValue(dgvSettings, row.Index, "Group");
                //var name = RowItemValue(dgvSettings, row.Index, "Name");
                if (DialogResult.OK != this.MsgBox($"确认删除{server}服务器{userName}用户的配置信息吗？", MessageBoxButtons.OKCancel))
                {
                    return;
                }
                var items = RuntimeContext.Current.GetRemoteSettings(a => a.UserName == userName && a.Server == server);
                var delItems = new List<IRemoteSetting>();
                items.ToList().ForEach(a =>
                {
                    delItems.Add(a.Clone());
                });
                if (RuntimeContext.Current.RemoveSetting(a => a.UserName == userName && a.Server == server))
                {
                    delItems.ForEach(a => FDHelper.Current.RemoteConfigChange(a, Models.ChangeType.DataRemove));
                }
                BindData(RuntimeContext.Current.RemoteSettings, bRefresh: true);
                FDHelper.Current.Save();
            }
            else if (e.ClickedItem.Text == MENU_NEW)
            {
                using (var fs = new FormSettings())
                {
                    if (DialogResult.OK == fs.ShowDialog())
                    {
                        _newConnectTo?.Invoke(fs.Result, AddToMenuItemType.Both);
                    }
                }
            }
            else if (e.ClickedItem.Text == MENU_COPY_PWD)
            {
                var row = dgvSettings.CurrentRow;
                if (row == null)
                    return;

                var password = RowItemValue(dgvSettings, row.Index, "Password");
                Clipboard.SetText(password);
            }
        }
        #endregion

        #region 按钮事件
        private void btnOK_Click(object sender, EventArgs e)
        {
            var server = txtServer.Text.Trim();
            var userName = txtUserName.Text.Trim();
            var status = (cmbStatus.SelectedItem as SettingStatus)?.Value ?? 0;
            Func<IRemoteSetting, string, bool> serverMatch = (config, strServer) =>
            {
                return config.Server.IgnoreCaseContains(strServer)
                       || config.Name.IgnoreCaseContains(strServer)
                    || config.Group.IgnoreCaseContains(strServer);
            };
            Predicate<IRemoteSetting> statusMatch = config =>
            {
                if (status == 0) return true;
                return config.IsEnable == (status == 1);
            };
            var result = RuntimeContext.Current.GetRemoteSettings(rs =>
            {
                if (!server.IsNullOrEmpty() && !userName.IsNullOrEmpty())
                {
                    return serverMatch(rs, server) && rs.UserName.IgnoreCaseContains(userName) && statusMatch(rs);
                }
                if (!server.IsNullOrEmpty())
                {
                    return serverMatch(rs, server) && statusMatch(rs);
                }
                if (!userName.IsNullOrEmpty())
                {
                    return rs.UserName.IgnoreCaseContains(userName) && statusMatch(rs);
                }
                return statusMatch(rs);
            }).ToList();

            BindData(result, true);
        }
        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
            DialogResult = DialogResult.Cancel;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            var list = new List<IRemoteSetting>();
            RemoteSetting rs;
            var props = typeof(RemoteSetting).GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            foreach (DataGridViewRow row in dgvSettings.Rows)
            {
                rs = new RemoteSetting();
                for (var i = 0; i < dgvSettings.ColumnCount; ++i)
                {
                    var column = dgvSettings.Columns[i];
                    var dcItem = (DataColumnItem)column.Tag;
                    var cell = row.Cells[i];
                    var value = cell.Value?.ToString();
                    if (!CheckEmpty(dcItem.IsRequired, () => value.IsNullOrEmpty(), dcItem.ErrMessage))
                    {
                        return;
                    }
                    var prop = props.FirstOrDefault(a => a.Name == column.Name);
                    var v = Convert.ChangeType(cell.Value, prop.PropertyType);
                    prop.SetValue(rs, v);

                }
                list.Add(rs);
            }
            RuntimeContext.Current.RemoveAll();
            RuntimeContext.Current.AddSettings(list);
            FDHelper.Current.Save();
            BindData(RuntimeContext.Current.RemoteSettings, true);
            this.MsgBox("保存成功");
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtServer.Text = txtUserName.Text = string.Empty;
            cmbStatus.SelectedIndex = 0;
            btnOK_Click(sender, e);
        }
        #endregion
        #endregion

        #region 逻辑处理

        private Func<DataGridView, int, string, string> RowItemValue = (dgv, rowIndex, name) =>
            {
                var value = dgv.Rows[rowIndex].Cells[name].Value;
                return value == null ? string.Empty : value.ToString();
            };

        private const int PageSize = 18;

        private void BindData(IList<IRemoteSetting> remoteSettings, bool bInitPager = false, bool bRefresh = false)
        {
            remoteSettings = remoteSettings.OrderBy(a => a.Group).ToList();
            if (bInitPager)
                dpSettings.InitData(remoteSettings, 1, PageSize);
            if (bRefresh)
                dpSettings.InitData(remoteSettings, dpSettings.PageIndex, PageSize);
            dgvSettings.DataSource = dpSettings.GetResult<IRemoteSetting>();
        }

        private void AddModelColumn<T>()
        {
            var dataItems = typeof(T).ToDataColumnItems().OrderBy(c => c.SortIndex);
            foreach (var columnItem in dataItems)
            {
                AddColumn(columnItem);
            }

        }

        private void AddColumn(DataColumnItem dataColumnItem)
        {
            DataGridViewColumn column;
            switch (dataColumnItem.DataColumnType)
            {
                case DataColumnType.CheckBox:
                    column = new DataGridViewCheckBoxColumn();
                    break;
                case DataColumnType.DateTime:
                case DataColumnType.Password:
                case DataColumnType.Text:
                    column = new DataGridViewTextBoxColumn();
                    break;
                case DataColumnType.Button:
                    column = new DataGridViewButtonColumn();
                    break;
                default:
                    column = new DataGridViewTextBoxColumn();
                    break;
            }

            column.Tag = dataColumnItem;
            column.Name = dataColumnItem.Name;
            column.DataPropertyName = dataColumnItem.DataName;
            column.HeaderText = dataColumnItem.Text;
            column.ToolTipText = dataColumnItem.Text;
            column.Width = dataColumnItem.Width;
            dgvSettings.Columns.Add(column);
        }
        private bool CheckEmpty(bool isRequired, Func<bool> condition, string msg)
        {
            if (isRequired && condition())
            {
                this.MsgBox(msg);
                return false;
            }

            return true;
        }

        private bool Check(Func<bool> action, string tip)
        {
            if (action())
            {
                this.MsgBox(tip);
                return false;
            }

            return true;
        }
    }


    #endregion

    public class Demo
    {
        [DataColumn(Text = "用户名")]
        public string UserName { get; set; }
        [DataColumn(Text = "密码", DataColumnType = DataColumnType.Password)]
        public string Password { get; set; }

        [DataColumn(Text = "信息")]
        public string Info { get; set; }
    }
}
